﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

// std headers
#include "TranslatorManager.h"
#include <algorithm>

// qt headers
#include <QString>

// custom headers
#include "IParameterDefinition.gcs.h"
#include "DebugMessage.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h" 


namespace gmepgcs
{
    IParameterDefinition::IParameterDefinition() :
        m_IsDrivingParameter(false),
        m_IsEssential(false),
        m_IsGeometry(false),
        m_IsInstance(false),
        m_IsOutputParameter(false),
        m_IsStandard(false),
        m_IsBuiltIn(false),
        m_IsShared(false),
        m_IsFromFile(false),
        m_IsModifiable(false),
        m_IsUserVisible(false)
    {
    }

    IParameterDefinition::~IParameterDefinition()
    {
    }

    bool IParameterDefinition::operator==(const IParameterDefinition & other)
    {
        if (m_Code != other.m_Code)
        {
            return false;
        }

        if (m_Formula != other.m_Formula)
        {
            return false;
        }

        if (m_GroupName != other.m_GroupName)
        {
            return false;
        }

        if (m_Id != other.m_Id)
        {
            return false;
        }

        if (m_IsDrivingParameter != other.m_IsDrivingParameter)
        {
            return false;
        }

        if (m_IsEssential != other.m_IsEssential)
        {
            return false;
        }

        if (m_IsGeometry != other.m_IsGeometry)
        {
            return false;
        }

        if (m_IsInstance != other.m_IsInstance)
        {
            return false;
        }

        if (m_IsStandard != other.m_IsStandard)
        {
            return false;
        }

        if (m_Name != other.m_Name)
        {
            return false;
        }
        if (m_ParameterDisplayType != other.m_ParameterDisplayType)
        {
            return false;
        }
        if (m_ParameterType != other.m_ParameterType)
        {
            return false;
        }   
        if (m_UnitSymbol != other.m_UnitSymbol)
        {
            return false;
        }

        if (m_UnitCode != other.m_UnitCode)
        {
            return false;
        }

        if (m_ValueType != other.m_ValueType)
        {
            return false;
        }

        if (m_IsBuiltIn != other.m_IsBuiltIn)
        {
            return false;
        }

        if (m_IsShared != other.m_IsShared)
        {
            return false;
        }

        if (m_IsFromFile != other.m_IsFromFile)
        {
            return false;
        }

        if (m_Description!= other.m_Description)
        {
            return false;
        }
        if (m_Guid != other.m_Guid)
        {
            return false;
        }
        if (m_Unit != other.m_Unit)
        {
            return false;
        }
        if (m_IsModifiable != other.m_IsModifiable)
        {
            return false;
        }
        if (m_IsUserVisible != other.m_IsUserVisible)
        {
            return false;
        }

        // compare enum values
        if (m_Values.size() != other.m_Values.size())
        {
            return false;
        }

        for (auto &thisEnumPair : m_Values)
        {
            auto otherEnumPairIterator = other.m_Values.find(thisEnumPair.first);
            if (otherEnumPairIterator == other.m_Values.end())
            {
                return false;
            }

            if (thisEnumPair.second != otherEnumPairIterator->second)
            {
                return false;
            }
            else
            {
                continue;
            }
        }

        return true;
    }

    bool IParameterDefinition::operator!=(const IParameterDefinition & other)
    {
        return !operator==(other);
    }

    std::shared_ptr<IParameterDefinition> IParameterDefinition::Clone()
    {
        std::shared_ptr<IParameterDefinition> spParameterDefinition = std::make_shared<IParameterDefinition>();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(spParameterDefinition, L"spParameterDefinition 为空", L"GMEP", L"2024-01-30");

        spParameterDefinition->m_Code = m_Code;
        spParameterDefinition->m_Formula = m_Formula;
        spParameterDefinition->m_GroupName = m_GroupName;
        spParameterDefinition->m_Id = m_Id;
        spParameterDefinition->m_IsDrivingParameter = m_IsDrivingParameter;
        spParameterDefinition->m_IsEssential = m_IsEssential;
        spParameterDefinition->m_IsGeometry = m_IsGeometry;
        spParameterDefinition->m_IsInstance = m_IsInstance;
        spParameterDefinition->m_IsOutputParameter = m_IsOutputParameter;
        spParameterDefinition->m_IsStandard = m_IsStandard;
        spParameterDefinition->m_Name = m_Name;
        spParameterDefinition->m_ParameterDisplayType = m_ParameterDisplayType;
        spParameterDefinition->m_ParameterType = m_ParameterType;
        spParameterDefinition->m_UnitSymbol = m_UnitSymbol;
        spParameterDefinition->m_UnitCode = m_UnitCode;
        spParameterDefinition->m_ValueType = m_ValueType;
        spParameterDefinition->m_IsBuiltIn = m_IsBuiltIn;
        spParameterDefinition->m_IsShared = m_IsShared;
        spParameterDefinition->m_IsFromFile = m_IsFromFile;
        spParameterDefinition->m_Description = m_Description;
        spParameterDefinition->m_Guid = m_Guid;
        spParameterDefinition->m_Unit = m_Unit;
        spParameterDefinition->m_IsModifiable = m_IsModifiable;
        spParameterDefinition->m_IsUserVisible = m_IsUserVisible;

        // clone enum values
        spParameterDefinition->m_Values = std::map<std::wstring, std::wstring>();
        for (auto &originEnumPair : m_Values)
        {
            spParameterDefinition->m_Values[originEnumPair.first] = originEnumPair.second;
        }

        return spParameterDefinition;
    }    
    
    bool IParameterDefinition::IsVisible()const
    {
        // 当参数的ParameterType为 “ElementId”时，不在UI上显示
        if (QString::compare(QString::fromStdWString(m_ParameterType), "ElementId", Qt::CaseInsensitive) == 0)
        {
            return false;
        }

        // 当参数的ParameterDisplayType为“时，不在UI上显示
        if (QString::compare(QString::fromStdWString(m_ParameterDisplayType), "NoDisplay", Qt::CaseInsensitive) == 0)
        {
            return false;
        }

        return true;
    }

    bool IParameterDefinition::IsDeleteable()const
    {
        // 对于内建参数
        if (m_IsBuiltIn)
        {
            return false;
        }

        // 对于几何参数
        if (m_IsGeometry)
        {
            return false;
        }

        // 对于标准参数
        if (m_IsStandard)
        {
            // 当参数为标准参数、且不是必要参数时，可删除
            if (!m_IsEssential)
            {
                return true;
            }
        }

        if (!m_IsGeometry && !m_IsStandard)
        {
            // 当参数为自定义参数、且不是驱动参数和被驱动参数时，可删除
            if (!m_IsDrivingParameter && !m_IsOutputParameter)
            {
                return true;
            }
        }

        return false;
    }

    bool IParameterDefinition::IsNameEditable()const
    {
        return false;
    }

    bool IParameterDefinition::IsUnitEditable()const
    {
        return false;
    }

    bool IParameterDefinition::IsInstanceEditable()const
    {
        return false;
    }

    bool gmepgcs::IParameterDefinition::IsGeometry()const
    {
        return m_IsGeometry;
    }

    const std::wstring& IParameterDefinition::GetCode()const
    {
        return m_Code;
    }
    void IParameterDefinition::SetCode(const std::wstring& code)
    {
        m_Code = code;
    }

    const std::wstring& IParameterDefinition::GetDescription()const
    {
        return m_Description;
    }
    void IParameterDefinition::SetDescription(const std::wstring& description)
    {
        m_Description = description;
    }

    const std::wstring& IParameterDefinition::GetFormula()const
    {
        return m_Formula;
    }
    void IParameterDefinition::SetFormula(const std::wstring& formula)
    {
        m_Formula = formula;
    }

    const std::wstring& IParameterDefinition::GetGroupName()const
    {
        return m_GroupName;
    }
    void IParameterDefinition::SetGroupName(const std::wstring& groupName)
    {
        m_GroupName = groupName;
    }

    const std::wstring& IParameterDefinition::GetGuid()const {
        return m_Guid;
    }
    void IParameterDefinition::SetGuid(const std::wstring& guid)
    {
        m_Guid = guid;
    }

    const std::wstring& IParameterDefinition::GetId()const
    {
        return m_Id;
    }
    void IParameterDefinition::SetId(const std::wstring& id)
    {
        m_Id = id;
    }

    const std::wstring& IParameterDefinition::GetName()const
    {
        return m_Name;
    }
    void IParameterDefinition::SetName(const std::wstring& name)
    {
        m_Name = name;
    }

    const std::wstring& IParameterDefinition::GetParamType()const
    {
        return m_ParameterType;
    }
    void IParameterDefinition::SetParamType(const std::wstring& paramType)
    {
        m_ParameterType = paramType;
    }

    const std::wstring& IParameterDefinition::GetParameterDisplayType()const
    {
        return m_ParameterDisplayType;
    }
    void IParameterDefinition::SetParameterDisplayType(const std::wstring& parameterDisplayType)
    {
        m_ParameterDisplayType = parameterDisplayType;
    }

    const std::wstring& IParameterDefinition::GetParameterType()const
    {
        return m_ParameterType;
    }
    void IParameterDefinition::SetParameterType(const std::wstring& parameterType)
    {
        m_ParameterType = parameterType;
    }

    const std::wstring& IParameterDefinition::GetUnitSymbol()const
    {
        return m_UnitSymbol;
    }
    void IParameterDefinition::SetUnitSymbol(const std::wstring& unitSymbol)
    {
        m_UnitSymbol = unitSymbol;
    }

    const std::wstring& IParameterDefinition::GetUnit()const
    {
        return m_Unit;
    }
    void IParameterDefinition::SetUnit(const std::wstring& unit)
    {
        m_Unit = unit;
    }

    const std::wstring& IParameterDefinition::GetUnitCode()const
    {
        return m_UnitCode;
    }
    void IParameterDefinition::SetUnitCode(const std::wstring& unitCode)
    {
        m_UnitCode = unitCode;
    }

    const std::wstring& IParameterDefinition::GetValueType()const
    {
        return m_ValueType;
    }
    void IParameterDefinition::SetValueType(const std::wstring& valueType)
    {
        m_ValueType = valueType;
    }
    bool IParameterDefinition::GetIsDrivingParameter()const
    {
        return m_IsDrivingParameter;
    }
    void IParameterDefinition::SetIsDrivingParameter(bool isDrivingParameter)
    {
        m_IsDrivingParameter = isDrivingParameter;
    }

    bool IParameterDefinition::GetIsEssential()const
    {
        return m_IsEssential;
    }
    void IParameterDefinition::SetIsEssential(bool isEssential)
    {
        m_IsEssential = isEssential;
    }

    bool IParameterDefinition::GetIsInstance()const
    {
        return m_IsInstance;
    }
    void IParameterDefinition::SetIsInstance(bool isInstance)
    {
        m_IsInstance = isInstance;
    }

    bool IParameterDefinition::GetIsModifiable()const
    {
        return m_IsModifiable;
    }
    void IParameterDefinition::SetIsModifiable(bool isModifiable)
    {
        m_IsModifiable = isModifiable;
    }

    bool IParameterDefinition::GetIsOutputParameter()const
    {
        return m_IsOutputParameter;
    }
    void IParameterDefinition::SetIsOutputParameter(bool isOutputParameter)
    {
        m_IsOutputParameter = isOutputParameter;
    }

    bool IParameterDefinition::GetIsStandard()const
    {
        return m_IsStandard;
    }
    void IParameterDefinition::SetIsStandard(bool isStandard)
    {
        m_IsStandard = isStandard;
    }

    bool IParameterDefinition::GetIsUserVisible()const
    {
        return m_IsUserVisible;
    }
    void IParameterDefinition::SetIsUserVisible(bool isUserVisible)
    {
        m_IsUserVisible = isUserVisible;
    }


    bool IParameterDefinition::GetIsBuiltIn()const
    {
        return m_IsBuiltIn;
    }
    void IParameterDefinition::SetIsBuiltIn(bool isBuiltIn)
    {
        m_IsBuiltIn = isBuiltIn;
    }

    bool IParameterDefinition::GetIsShared()const
    {
        return m_IsShared;
    }
    void IParameterDefinition::SetIsShared(bool isShared)
    {
        m_IsShared = isShared;
    }
    void IParameterDefinition::SetIsGeometry(bool isGeometry)
    {
        m_IsGeometry = isGeometry;
    }

    bool IParameterDefinition::GetIsFromFile()const
    {
        return m_IsFromFile;
    }
    void IParameterDefinition::SetIsFromFile(bool isFromFile)
    {
        m_IsFromFile = isFromFile;
    }
}